package com.fmatos.amazingwallpapers.image;

import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;

import javax.inject.Inject;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import android.content.Context;
import android.util.Log;

import com.fmatos.amazingwallpapers.image.database.orm.Album;
import com.fmatos.amazingwallpapers.image.database.orm.DatabaseHelper;
import com.fmatos.amazingwallpapers.image.database.orm.DatabaseManager;
import com.fmatos.amazingwallpapers.image.database.orm.Photo;
import com.fmatos.amazingwallpapers.image.database.orm.repository.AlbumRepo;
import com.fmatos.amazingwallpapers.image.database.orm.repository.PhotoRepo;
import com.fmatos.amazingwallpapers.image.network.CloudClient;
import com.fmatos.amazingwallpapers.image.network.CloudHelper;
import com.fmatos.amazingwallpapers.image.network.dto.RemoteAlbumInfo;
import com.fmatos.amazingwallpapers.image.network.dto.RemotePhoto;
import com.fmatos.amazingwallpapers.imagemanagement.FileManager;
import com.fmatos.amazingwallpapers.view.albums.AlbumsViewSource.AlbumViewDto;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.dao.Dao;

/**
 * Manages network clients and database info seamlessly
 * @author fdematos
 *
 */
public class CloudManager {

	private static final String TAG = CloudManager.class.getSimpleName();

	private static final DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");

	protected CloudClient cloudClient;
	protected FileManager fileManager;

	private CloudHelper cloudHelper;

	private AlbumRepo albumRepo;
	private PhotoRepo photoRepo;

	@Inject
	public CloudManager(Context context,AlbumRepo albumRepo,PhotoRepo photoRepo) {
		this.albumRepo = albumRepo;
		this.photoRepo = photoRepo;
		acquireResources(context);
	}

	protected void acquireResources(Context context)	{
		cloudClient = new CloudClient(context);
		fileManager = new FileManager(context);
		cloudHelper = new CloudHelper();
	
	}

	/**
	 * Gets fresh list of albums from server and gets newest urls for all albums
	 */
	public void refreshAlbumList() {
		List<RemoteAlbumInfo> albumsList = cloudClient.getAlbumsList();

		try {
			storeAlbumsList(albumsList);
		} catch (SQLException e) {
			e.printStackTrace();
		}

		try {
			refreshAllAlbums();
		} catch (SQLException e) {
			e.printStackTrace();
		}		
	}

	private void storeAlbumsList(List<RemoteAlbumInfo> albumsList) throws SQLException {
		if ( albumsList == null ) {
			return;
		}

		for (RemoteAlbumInfo remoteAlbum : albumsList ) {
			Album album = new Album();
			album.setName(remoteAlbum.getName());
			album.setNiceName(remoteAlbum.getNiceName());
			album.setUrl(remoteAlbum.getUrl());

			if ( remoteAlbum.getDate() != null ) {
				album.setUpdateTime(formatter.parseDateTime(remoteAlbum.getDate()).getMillis());
			}

			//			Log.i(TAG,"Insert " + album.getNiceName());

			albumRepo.createAlbum(album);
		}		
	}

	private void refreshAllAlbums() throws SQLException {

		List<Album> albumsList = albumRepo.getAlbums();

		for (Album album : albumsList) {
			refreshAlbumInfo(album);
		}
	}

	/**
	 * Downloads photo info for particular album
	 * @param albumName
	 * @throws SQLException 
	 */
	private void refreshAlbumInfo(Album album) throws SQLException {

		if ( album == null ) {
			return;
		}

		// gets list of photos for a particular album
		RemoteAlbumInfo remoteAlbum =  cloudClient.getAlbumInfo(album.getUrl());

		if (remoteAlbum != null ) {
			if ( remoteAlbum.getPhotos() != null ) {
				Log.d(TAG,"Inserting " + remoteAlbum.getPhotos().size() + " photos on " + album.getNiceName());
			}
			insertPhotos(remoteAlbum,album.getName());

			if ( remoteAlbum.getDate() != null ) {
				DateTime dtUpdateTime = formatter.parseDateTime(remoteAlbum.getDate());
				album.setUpdateTime(dtUpdateTime.getMillis());
				albumRepo.updateAlbum(album);

			}
		}

		//		Log.d(TAG,"Download new photos for album " + album.getNiceName() );

	}

	/**
	 * Downloads photos info for particular album
	 * @param albumName
	 */
	public void refreshAlbumInfo(String albumName) {
		if ( albumName == null ) {
			return;
		}

		List<Photo> photos =  photoRepo.getPhotosFromAlbum(albumName); 

		Log.i(TAG,"photo count = " + photos.size());
		for ( Photo photo : photos) {
			if ( photo.getFilePath() == null || ! fileManager.isImageHealthy(photo.getFilePath()) ) {
				String path = downloadFile(photo.getUrl());
				photo.setFilePath(path);
				photo.setGif(fileManager.isImageGif(path));
				photo.setCorrupt(! fileManager.isImageHealthy(path));

				Log.i(TAG,"Downloaded photo " + albumName + " to " + path + " / " + photo.isCorrupt() + "/" + photo.isGif());
				photoRepo.update(photo);
			}
		}



	}

	private String downloadFile(String url) {
		InputStream istream = cloudHelper.downloadImage(url);

		String path = fileManager.writeFileToRandomPath(istream, "newDownload-"); 

		return path;
	}

	/**
	 * Insert photos in the database
	 * @param remoteAlbum
	 * @param albumName
	 */
	private void insertPhotos(RemoteAlbumInfo remoteAlbum, String albumName) {

		if ( remoteAlbum == null || remoteAlbum.getPhotos() == null ) {
			return;
		}

		for (RemotePhoto remotePhoto : remoteAlbum.getPhotos() ) {
			Photo photo = new Photo();
			photo.setAlbumName(remoteAlbum.getName());
			photo.setUrl(getSafeUrl(remotePhoto.getUrl()));

			photo.setCaption(remotePhoto.getCaption());
			photo.setDescription(remotePhoto.getDescription());
			photo.setDate(remotePhoto.getDate());

			photoRepo.create(photo);
		}


	}

	private String getSafeUrl(String url) {
		String safeUrl = url;

		if ( safeUrl.contains(" ")) {
			safeUrl = url.split(" ")[0]; // JPL is breaking this!
		}

		return safeUrl;
	}

	/**
	 * Download photo urls from album, stores in photos database
	 * @param albumDto
	 */
	public void downloadAlbumPhotos(AlbumViewDto albumDto) {
		if ( albumDto != null ) {
			return;
		}		
	}

	/**
	 * Delete old photos for album
	 * @param name
	 */
	public void deleteAlbumOldPhotos(String name) {
		if ( name != null ) {
			return;
		}		
	}	

	/**
	 * Scans folder for images that doesn't appear in the database
	 */
	public void cleanAlbumOldPhotos() {

	}


	/**
	 * Downloads a single photo from network. Very usefull to fill in missing photos when
	 * an activity is about to display them
	 * @param thumbnailUrl
	 */
	public void getPhotoFromNetwork(String thumbnailUrl) {

		Photo photo = null;
		photo = photoRepo.getPhoto(thumbnailUrl);

		if ( photo != null ) {

			// double checking whether image has been recently downloaded
			if (photo.getFilePath() == null || ! fileManager.isImageHealthy(photo.getFilePath())) {
				Log.d(TAG,"Downloading photo " + thumbnailUrl);
				String filename = cloudClient.getPhotoFromNetwork(thumbnailUrl);
				if ( fileManager.isImageHealthy(filename)) {
					Log.d(TAG,"Downloaded  photo was healthy: " + thumbnailUrl);
					photo.setFilePath(filename);
					photo.setGif(fileManager.isImageGif(filename));
				} else {
					photo.setCorrupt(true);
				}
				photoRepo.update(photo);
			}
		}

	}	
}
